using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content;

namespace G4KFramework
{
    class GSharedContentManager : ContentManager
    {
        static CommonContentManager _common;
        List<string> _loadedAssets;

        public GSharedContentManager(IServiceProvider serviceProvider, string rootDirectory)
            : base(serviceProvider, rootDirectory)
        {
            if (_common == null)
                _common = new CommonContentManager(ServiceProvider, RootDirectory);
            _loadedAssets = new List<string>();
        }

        public override T Load<T>(string assetName)
        {
            _loadedAssets.Add(assetName);
            return _common.Load<T>(assetName);
        }

        public override void Unload()
        {
            if (_loadedAssets == null)
                throw new ObjectDisposedException(typeof(GSharedContentManager).Name);

            _common.Unload(this);
            _loadedAssets = null;

            base.Unload();
        }

        //-----------------------------------------------------------------
        // Class CommonContenManager
        class CommonContentManager : ContentManager
        {
            readonly Dictionary<string, ReferencedAsset> _references;

            public CommonContentManager(IServiceProvider serviceProvider, string rootDirectory)
                : base(serviceProvider, rootDirectory)
            {
                _references = new Dictionary<string, ReferencedAsset>();
            }

            public override T Load<T>(string assetName)
            {
                ReferencedAsset refAsset;
                if (!_references.TryGetValue(assetName, out refAsset))
                {
                    refAsset = new ReferencedAsset { Asset = ReadAsset<T>(assetName, null) };
                    _references.Add(assetName, refAsset);
                }
                refAsset.References++;

                return (T)refAsset.Asset;
            }

            public void Unload(GSharedContentManager container)
            {
                foreach (var assetName in container._loadedAssets)
                {
                    var refAsset = _references[assetName];
                    refAsset.References--;
                    if (refAsset.References == 0)
                    {
                        if (refAsset.Asset is IDisposable)
                            (refAsset as IDisposable).Dispose();
                        _references.Remove(assetName);
                    }
                }
            }
        }

        class ReferencedAsset
        {
            public object Asset;
            public int References;
        }
    }
}
